Skip to content

Conversation

@Uli-Z
Copy link
Contributor

@Uli-Z Uli-Z commented Nov 17, 2025

Background

Discussion status and references:

Problem statement:

  • Participant columns encode “signed shares,” which are neither clear personal costs nor per‑expense balances; this makes the export unintuitive compared to the JSON data model.
  • Reimbursements appear as expenses, distorting totals and requiring a special flag.

Proposed direction:

  • Switch participant columns to per‑expense saldo (payer advances; others owe). Model reimbursements as internal transfers by using Cost=0.

Why now:

Summary

This PR switches the CSV export to a per‑expense saldo format that aligns better with user expectations and spreadsheet workflows. Participant columns carry the net effect (saldo) of each expense. Reimbursements use Cost=0, which removes the need for a dedicated reimbursement flag.

Changes

  • Columns
    • Keep: Date, Description, Category, Currency, Cost, Original cost, Original currency, Conversion rate, Split mode, Paid By.
    • Remove: Is Reimbursement (redundant once reimbursements use Cost=0).
    • Participant columns: per‑expense saldos (payer positive advance; others negative owed amounts).
  • Behaviour
    • Reimbursements: exported as internal transfers with Cost=0; participant saldos reflect direction/amount.
    • Incomes: negative Cost values; participant saldos remain consistent.
    • Sorting: consistent with JSON export (by expenseDate, then createdAt).
  • Implementation
    • CSV route updated to compute participant saldos; paid amounts and conversion values normalized to plain numbers before formatting.

CSV Format (Descriptive)

  • Fixed columns: Date, Description, Category, Currency, Cost, Original cost, Original currency, Conversion rate, Split mode, Paid By.
  • Participant columns: per‑expense saldo per participant.
  • Semantics:
    • Payer: saldo = totalAmount - ownShareAmount (advance for others).
    • Others: saldo = - ownShareAmount (owed to the payer).
  • Special cases:
    • Reimbursements → Cost = 0 (internal transfer; not group spending).
    • Incomes → negative Cost (distribution to participants).

Testing

  • Manual: export CSVs for classical expenses, altruist payments, self‑payments, incomes, and reimbursements; verify that “who owes whom” is directly readable and that reimbursements use Cost=0.
  • Script‑assisted: run the CSV→sentences helper (attached) to cross‑check narrative output and totals.

Rationale

  • Practical and close to intent: participant columns show the real‑world effect per expense (advance vs. owed), matching users’ mental model and spreadsheet usage.
  • Trade‑off: the exact split method (shares/percentages) is not serialized; amounts are. In practice, amounts are what downstream tools operate on.
  • Clarity: Is Reimbursement becomes unnecessary with Cost=0; totals remain correct and the transfer direction is visible in participant columns.

Why remove the Is Reimbursement column?

  • Reimbursements are internal transfers, not spending. Using Cost=0 keeps group totals correct without an extra flag.
  • The participant columns already encode direction and amount; the boolean adds no additional value.

Evidence

  • Exercised against a comprehensive set of scenarios (classical expenses, altruist payments, self‑payments, incomes, reimbursements) using a CSV→sentences helper and curated test CSVs (attached via PR comment).

Files for testing

testcases.csv
convert-csv-to-sentences.py

Jessica1213 and others added 4 commits December 7, 2025 20:26
…th last-share remainder\n\nPreviously, participant shares were computed in major units and rounded per-participant before saldo calculation. For amounts like 1.01 split across 2 people, this caused mismatches (e.g. -0.51 and +0.50) where per‑row saldos did not add up due to early rounding.\n\nThis change mirrors app behaviour: compute shares in minor units (cents), distribute floor(amount*share/total) incrementally and assign the remainder to the last relevant participant. Saldos are derived from these integer shares and only formatted at the end. This fixes the erroneous rounding assignment and keeps totals consistent.
@Uli-Z Uli-Z force-pushed the feature/csv-export-saldo-revamp branch from eb22c9e to c7d7401 Compare December 7, 2025 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants